import base64
import pickle
from pathlib import Path
from typing import Callable

import yaml
from PySide6.QtWidgets import QMessageBox

from utils.settings import ASSETS_DIR


class ConstItem:
    __slots__ = ['value', 'label']

    def __init__(self, value, label):
        self.value = value
        self.label = label

    def __eq__(self, other: 'ConstItem'):
        if other is None:
            return False

        if isinstance(other, str):
            return self.value == other

        return self.value == other.value

    def __str__(self):
        return self.label

    def __hash__(self):
        return hash(self.value)


class ConstItemWithColor(ConstItem):
    __slots__ = ConstItem.__slots__ + ['color']

    def __init__(self, value, label, color):
        super().__init__(value, label)

        self.color = color


class ValueRange:
    __slots__ = ('current', 'maximum')

    def __init__(self, maximum, current=None):
        self.maximum = maximum
        self.current = maximum if current is None else current

    def __str__(self):
        return f'{self.current}/{self.maximum}'

    def __json__(self):
        return str(self)

    def load(self, s: str):
        current, maximum = s.split('/')
        self.current = int(current)
        self.maximum = int(maximum)

    def rate(self):
        return f'{round(100 * self.current / self.maximum, 2)}%'


def dumps(obj):
    return base64.b64encode(pickle.dumps(obj)).decode()


def loads(s):
    return pickle.loads(base64.b64decode(s.encode()))


def iter_dir(p: Path):
    for sub_p in p.iterdir():
        if sub_p.is_dir():
            yield from iter_dir(sub_p)
        else:
            yield sub_p


def message_box_information(msg: str):
    QMessageBox.information(None, '提示', msg)


def read_yaml(p: str, _iter=True):
    with open(ASSETS_DIR / p, 'r', encoding='utf-8') as f:
        result: dict = yaml.safe_load(f)
        if not _iter:
            return result

    return ((k, v) for k, v in result.items())


def fast_json(obj):
    result = dict()
    for key, value in obj.__dict__.items():
        if key.startswith('__'):
            continue

        if isinstance(value, Callable):
            continue

        result[key] = value

    return result
